package com.eleventwelve.iris.web.controller;

import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.opentides.bean.SystemCodes;
import org.opentides.editor.BaseEntityEditor;
import org.opentides.service.SystemCodesService;
import org.springframework.validation.BindException;
import org.springframework.validation.Errors;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractWizardFormController;

import com.eleventwelve.iris.entity.Allergen;
import com.eleventwelve.iris.entity.ContactNumber;
import com.eleventwelve.iris.entity.Disease;
import com.eleventwelve.iris.entity.Patient;
import com.eleventwelve.iris.service.AllergenService;
import com.eleventwelve.iris.service.ContactNumberService;
import com.eleventwelve.iris.service.DiseaseService;
import com.eleventwelve.iris.service.PatientAllergyService;
import com.eleventwelve.iris.service.PatientDiseaseService;
import com.eleventwelve.iris.service.PatientService;
import com.eleventwelve.iris.web.validator.PatientRegistrationValidator;

/**
 * 
 * @author Ashley
 *
 */
@SuppressWarnings("deprecation")
public class PatientRegistrationController extends AbstractWizardFormController{
	private String successView;
	private String cancelView;
	private PatientService patientService;
	private SystemCodesService systemCodesService;
	private AllergenService allergenService;
	private ContactNumberService contactNumberService;
	private PatientAllergyService patientAllergyService;
	private DiseaseService diseaseService;
	private PatientDiseaseService patientDiseaseService;
	
	
	@Override
	protected Map<String, Object> referenceData(HttpServletRequest request, Object command,
			Errors errors, int page) throws Exception {
		Map<String, Object> map = new HashMap<String, Object>();
		
		switch (page) {
		case 0:
			List<SystemCodes> genders = systemCodesService.findSystemCodesByCategory("GENDER");
			Collections.reverse(genders);
			map.put("genders", genders);
			map.put("numberTypes", systemCodesService.findSystemCodesByCategory("NUMBER_TYPE"));
			break;
		case 1:
			map.put("allergyStatus", systemCodesService.findSystemCodesByCategory("ALLERGY_STATUS"));
			map.put("diseaseStatus", systemCodesService.findSystemCodesByCategory("DISEASE_STATUS"));
			map.put("allergens", allergenService.findAll());
			map.put("diseases", diseaseService.findAll());
			break;
		default:
			break;
		}
		
		return map;
	}
	
	@Override
	protected Object formBackingObject(HttpServletRequest request)
			throws Exception {
		Patient patient = new Patient();
		patient.setRegistrationDate(new Date());
		
		return patient;
	}
	
	@Override
	protected void initBinder(HttpServletRequest request,
			ServletRequestDataBinder binder) throws Exception {
		binder.registerCustomEditor(SystemCodes.class, new BaseEntityEditor(systemCodesService));
		binder.registerCustomEditor(ContactNumber.class, new BaseEntityEditor(contactNumberService));
		binder.registerCustomEditor(Allergen.class, new BaseEntityEditor(allergenService));
		binder.registerCustomEditor(Disease.class, new BaseEntityEditor(diseaseService));
	}
	
	
	@Override
	protected ModelAndView processFinish(HttpServletRequest request,
			HttpServletResponse response, Object obj, BindException exception)
			throws Exception {
		
		Patient patient = (Patient) obj;
		patientService.save(patient);	//we save the patient first
		
		contactNumberService.savePatientContactNumbers(patient);	//we save contact numbers separately to avoid error with saving an unsaved transient instance
		
		patientAllergyService.savePatientAllergies(patient);		//to avoid saving an unsaved transient instance
		
		patientDiseaseService.savePatientDisease(patient);			//to avoid saving an unsaved transient instance
		
		return new ModelAndView("redirect:patient.jspx?id="+patient.getId());
	}
	
	@Override
	protected void validatePage(Object command, Errors errors, int page) {
		PatientRegistrationValidator validator = (PatientRegistrationValidator) getValidator();
		switch (page) {
		case 0:
			validator.validatePage1Form(command, errors);
			break;

		default:
			break;
		}
	}
	

	public String getSuccessView() {
		return successView;
	}

	public void setSuccessView(String successView) {
		this.successView = successView;
	}

	public String getCancelView() {
		return cancelView;
	}

	public void setCancelView(String cancelView) {
		this.cancelView = cancelView;
	}


	public PatientService getPatientService() {
		return patientService;
	}


	public void setPatientService(PatientService patientService) {
		this.patientService = patientService;
	}


	public SystemCodesService getSystemCodesService() {
		return systemCodesService;
	}


	public void setSystemCodesService(SystemCodesService systemCodesService) {
		this.systemCodesService = systemCodesService;
	}

	public AllergenService getAllergenService() {
		return allergenService;
	}

	public void setAllergenService(AllergenService allergenService) {
		this.allergenService = allergenService;
	}

	public ContactNumberService getContactNumberService() {
		return contactNumberService;
	}

	public void setContactNumberService(ContactNumberService contactNumberService) {
		this.contactNumberService = contactNumberService;
	}

	public PatientAllergyService getPatientAllergyService() {
		return patientAllergyService;
	}

	public void setPatientAllergyService(PatientAllergyService patientAllergyService) {
		this.patientAllergyService = patientAllergyService;
	}

	public DiseaseService getDiseaseService() {
		return diseaseService;
	}

	public void setDiseaseService(DiseaseService diseaseService) {
		this.diseaseService = diseaseService;
	}

	public PatientDiseaseService getPatientDiseaseService() {
		return patientDiseaseService;
	}

	public void setPatientDiseaseService(PatientDiseaseService patientDiseaseService) {
		this.patientDiseaseService = patientDiseaseService;
	}

}
